/**
 * @file    CommunicationEvents.h
 * @brief   Collects events (wosh::Fact extension) related to communication.
 *
 ****************************************************************************
 * @version 0.8.399 $Id: CommunicationEvents.h 2809 2010-07-30 05:20:06Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

#ifndef __WOSH_Entertainment_CommunicationEvents_H__
 #define __WOSH_Entertainment_CommunicationEvents_H__

 #include <woshDefs.h>
 #include <core/Fact.h>
 #include <core/User.h>
 #include <interfaces/services/CommunicatorService.h>

 
namespace wosh {
 namespace communication {

/**
 * @class   wosh::communication::UserPresence_StateChanged
 * @brief   Raised when user presence is changed (such as online to offline).
 *
 * Internally, data is stored as wosh::List. Supports also wosh::Variant type.
 *
 * Fields are:
 *  - \c username [Variant::STRING] (always present, first item of the list)
 *  - \c presence_state [Variant::INTEGER] (optional, second item of the list)
 *  - \c previous_last_seen (optional, third item of the list)
 *
 * Some getters are provided for convenience:
 * \code
void CommunicatorWatcher::busMessage( const Message& message, const Bus* source ) {
	if ( message.isEmpty() ) return;
	if ( message.getContent()->isFact() ) {
		if ( message.getContent()->isKindOf<wosh::communication::UserPresence_StateChanged>() ) {
			const wosh::communication::UserPresence_StateChanged* upEvent = message.getContent()->as<wosh::communication::UserPresence_StateChanged>();
			this->users.transactionBeginWrite();
			User* cUser = this->users.find( upEvent->getUserName() );
			if ( cUser == NULL ) {
				this->users.transactionEnd();
				return;
			 }
			int64 timestamp = message.getTimestamp();
			if ( upEvent->getPresenceState() & _CommunicatorService_Presence_Offline || upEvent->getPresenceState() == _CommunicatorService_Presence_Unknown )
				cUser->updateCommmunicator(message.getSource().toString(), -timestamp);
			else if ( upEvent->getPresenceState() & _CommunicatorService_Presence_Online )
				cUser->updateCommmunicator(message.getSource().toString(), timestamp);
			this->users.transactionEnd();
		 }
	 }
 }
 * \endcode
 *
 * @see     wosh::Fact
 * @see     wosh::interfaces::services::CommunicatorService
 ****************************************************************************
 * @version 0.8.399 $Id: CommunicationEvents.h 2809 2010-07-30 05:20:06Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
class UserPresence_StateChanged : public wosh::Fact
 {
	WOSH_SERIALIZABLE(wosh::communication::UserPresence_StateChanged)

	public:
		/**
		 * @brief  Empty constructor.
		 */
		UserPresence_StateChanged()
			: wosh::Fact(_CommunicatorService_EVENT_PresenceChanged) { }
		/**
		 * @brief  Constructor with initializers.
		 * @param username [in] the subject (username) of the event
		 * @param presence_state [in] the current (new) presence state 
		 * @param previous_last_seen [in] timestamp of previous state
		 */
		UserPresence_StateChanged( const std::string& username, User::PRESENCE presence_state, long previous_last_seen = 0 );
		/**
		 * @brief  Copy constructor.
		 * @param m [in] the source object to be copied
		 */
		UserPresence_StateChanged( const UserPresence_StateChanged& m )
			: wosh::Fact(m) { }
		/**
		 * @brief  Empty destructor.
		 */
		virtual ~UserPresence_StateChanged() { }

	public:
		/**
		 * @brief   Get the (wosh) username (subject of the event)
		 * @return  string representing the (wosh) username; empty string on errors/missing data
		 * @note    Value is extracted from the wosh::Fact's content,
		 *          wosh::Variant (Variant::STRING) and List (first item as Variant)
		 *          types are supported.
		 */
		std::string getUserName() const;
		/**
		 * @brief   Get the presence state of the user.
		 * @return  integer value defined in wosh::interfaces::services::CommunicatorService;
		 *          _CommunicatorService_Presence_Unknown on errors/missing data
		 * @note    Value is extracted from the wosh::Fact's content,
		 *          only List is supported (second item as numeric Variant)
		 *          types are supported.
		 */
		User::PRESENCE getPresenceState() const;

		inline bool isUserOnline() const			{ return ( (getPresenceState() & User::PRESENCE_ONLINE) == User::PRESENCE_ONLINE ); }
		inline bool isUserOffline() const			{ return ( (getPresenceState() & User::PRESENCE_OFFLINE) == User::PRESENCE_OFFLINE ); }

		long getPreviousLastSeen() const;
		/**
		 * @brief   Get presence state as a literal string
		 * @return  presence state as literal string
		 * @note    integer values are defined in wosh::interfaces::services::CommunicatorService;
		 */
		inline const char* getPresenceAsString() const {
			return User::getUserPresenceAsString( getPresenceState() );
		 }

}; // class def


// -------------------------------------------------------------------------------------------------------


/**
 * @class   wosh::communication::UserInteraction_Event
 * @brief   Raised when user confirms the presence interacting with the service/device.
 *
 * Internally, data is stored as wosh::Variant (STRING).
 *
 * Fields are:
 *  - \c username [Variant::STRING]
 *
 * UserInteraction_Event::getUserName() method is provided for convenience:
 * \code
void CommunicatorWatcher::busMessage( const Message& message, const Bus* source ) {
	if ( message.isEmpty() ) return;
	if ( message.getContent()->isFact() ) {
		if ( message.getContent()->isKindOf<wosh::communication::UserInteraction_Event>() ) {
			const wosh::communication::UserInteraction_Event* upEvent = message.getContent()->as<wosh::communication::UserInteraction_Event>();
			this->users.transactionBeginWrite();
			User* cUser = this->users.find( upEvent->getUserName() );
			if ( cUser == NULL ) {
				this->users.transactionEnd();
				return;
			 }
			int64 timestamp = message.getTimestamp();
			cUser->updateCommmunicator(message.getSource().toString(), timestamp);
			this->users.transactionEnd();
		 }
	 }
 }
 * \endcode
 *
 * @see     wosh::Fact
 * @see     wosh::interfaces::services::CommunicatorService
 ****************************************************************************
 * @version 0.8.399 $Id: CommunicationEvents.h 2809 2010-07-30 05:20:06Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
class UserInteraction_Event : public wosh::Fact
 {
	WOSH_SERIALIZABLE(wosh::communication::UserInteraction_Event)

	public:
		/**
		 * @brief  Empty constructor.
		 */
		UserInteraction_Event()
			: wosh::Fact( _CommunicatorService_EVENT_UserInteraction ) { }
		/**
		 * @brief  Constructor with initializers.
		 * @param username [in] the subject (username) of the event
		 */
		UserInteraction_Event( const std::string& username );
		/**
		 * @brief  Copy constructor.
		 * @param m [in] the source object to be copied
		 */
		UserInteraction_Event( const UserInteraction_Event& m )
			: wosh::Fact(m) { }
		/**
		 * @brief  Empty destructor.
		 */
		virtual ~UserInteraction_Event() { }

	public:
		/**
		 * @brief   Get the (wosh) username (subject of the event)
		 * @return  string representing the (wosh) username; empty string on errors/missing data
		 * @note    Value is extracted from the wosh::Fact's content,
		 *          wosh::Variant (Variant::STRING) and List (first item as Variant)
		 *          types are supported.
		 */
		std::string getUserName() const;

}; // class def



// -------------------------------------------------------------------------------------------------------


/**
 * @class   wosh::communication::UserLogging_Event
 * @brief   Raised when user logs in/out (usually to a wosh::Session).
 *
 * Internally, data is stored as wosh::Variant (STRING).
 *
 * Fields are:
 *  - \c username [Variant::STRING]
 *
 * UserLogging_Event::getUserName() method is provided for convenience:
 * \code

 * \endcode
 *
 * @see     wosh::Fact
 * @see     wosh::interfaces::services::CommunicatorService
 ****************************************************************************
 * @version 0.8.399 $Id: CommunicationEvents.h 2809 2010-07-30 05:20:06Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
class UserLogging_Event : public wosh::Fact
 {
	WOSH_SERIALIZABLE(wosh::communication::UserLogging_Event)

	public:
		/**
		 * @brief  Empty constructor.
		 */
		UserLogging_Event()
			: wosh::Fact( _CommunicatorService_EVENT_UserLogging ) { }
		/**
		 * @brief  Constructor with initializers.
		 * @param username [in] the subject (username) of the event
		 */
		UserLogging_Event( const std::string& username );
		/**
		 * @brief  Copy constructor.
		 * @param m [in] the source object to be copied
		 */
		UserLogging_Event( const UserLogging_Event& m )
			: wosh::Fact(m) { }
		/**
		 * @brief  Empty destructor.
		 */
		virtual ~UserLogging_Event() { }

	public:
		/**
		 * @brief   Get the (wosh) username (subject of the event)
		 * @return  string representing the (wosh) username; empty string on errors/missing data
		 * @note    Value is extracted from the wosh::Fact's content,
		 *          wosh::Variant (Variant::STRING) and List (first item as Variant)
		 *          types are supported.
		 */
		std::string getUserName() const;

}; // class def





 }; // namespace communication
}; // namespace wosh


#endif //__WOSH_Entertainment_CommunicationEvents_H__
